/**
 * @作者 faner
 * @创建时间 2021/2/19 16:10
 */
package com.faner.fast.security.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.faner.fast.constant.CacheConstants;
import com.faner.fast.constant.CommonConstants;
import com.faner.fast.upms.domain.bo.UserInfoBO;
import com.faner.fast.upms.domain.dto.SysUserDTO;
import com.faner.fast.upms.domain.vo.SysUserVO;
import com.faner.fast.upms.model.SysUserDO;
import com.faner.fast.upms.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

@Slf4j
@Service("fastUserDetailsService")
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FastUserDetailsServiceImpl implements UserDetailsService {

    private final SysUserService sysUserService;

    private final CacheManager cacheManager;

    /**
     * 用户密码登录
     * @param username 用户名
     * @return
     */
    @Override
    @SneakyThrows
    public UserDetails loadUserByUsername(String username) {
        Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
        if (cache != null && cache.get(username) != null) {
            return (FastUser) cache.get(username).get();
        }
        SysUserDO user = sysUserService.getOne(Wrappers.<SysUserDO>query().lambda().eq(SysUserDO::getUsername, username));
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        UserInfoBO userInfo = sysUserService.getUserInfo(user);
        UserDetails userDetails = getUserDetails(userInfo);
        if (cache != null) {
            cache.put(username, userDetails);
        }
        return userDetails;
    }

    /**
     * 构建userdetails
     * @param info 用户信息
     * @return
     */
    private UserDetails getUserDetails(UserInfoBO info) {
        Set<String> dbAuthsSet = new HashSet<>();
        if (ArrayUtil.isNotEmpty(info.getRoles())) {
            // 获取角色
            Arrays.stream(info.getRoles()).forEach(role -> dbAuthsSet.add(CommonConstants.ROLE + role));
            // 获取资源
            dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));

        }
        Collection<? extends GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(dbAuthsSet.toArray(new String[0]));
        SysUserDO user = info.getSysUser();

        // 构造security用户
        return new FastUser(user.getId(), user.getDeptId(), user.getUsername(),
                user.getPassword(),
                StrUtil.equals(user.getLockFlag(), CommonConstants.STATUS_NORMAL), authorities);
    }

}
